#ifndef THREADPOOL_H
#define THREADPOOL_H
#include <vector>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <atomic>
#include <future>

class ThreadPool {
public:
    // 构造函数：创建指定数量的工作线程
    ThreadPool(size_t threads) : stop(false) {
        for (size_t i = 0; i < threads; ++i)
            // 每个工作线程都运行 worker_loop 函数
            workers.emplace_back([this] { worker_loop(); });
    }

    // 模板函数 enqueue：将任务添加到队列
    template<typename F, typename... Args>
    auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
        // 获取任务的返回类型
        using ReturnType = decltype(f(args...));

        // 创建一个 packaged_task，用于包装任务函数及其参数
        // std::bind 用于将函数 f 和参数 args 绑定成一个无参调用
        // std::forward 用于完美转发参数
        // auto task = std::make_shared<std::packaged_task<ReturnType()>>(
        //     std::bind(std::forward<F>(f), std::forward<Args>(args)...)
        // );
        // 如果是成员函数，需要绑定 this 指针
        auto task = std::make_shared<std::packaged_task<ReturnType()>>(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...)
        );

        // 从 packaged_task 获取 future 对象，用于稍后获取任务结果
        std::future<ReturnType> res = task->get_future();
        {
            std::unique_lock<std::mutex> lock(queue_mutex);

            // 关键改进：如果线程池已停止，则不允许添加新任务
            if (stop) {
                throw std::runtime_error("enqueue on stopped ThreadPool");
            }

            // 将任务（一个调用 packaged_task 的 lambda）添加到任务队列
            // 这个 lambda 捕获了 task (shared_ptr)，确保 packaged_task 的生命周期
            tasks.emplace([task]() { (*task)(); });
        }
        // 通知一个等待的工作线程有新任务可用
        condition.notify_one();
        return res;
    }

    // 析构函数：停止所有工作线程并等待它们完成
    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            // 设置停止标志
            stop = true;
        }
        // 通知所有等待的线程，以便它们检查停止标志并退出
        condition.notify_all();
        // 等待所有工作线程完成它们的当前任务并退出
        for (std::thread& worker : workers)
            worker.join();
    }

private:
    // 工作线程的主循环函数
    void worker_loop() {
        while (true) {
            std::function<void()> task;
            {
                std::unique_lock<std::mutex> lock(queue_mutex);
                // 等待条件：线程池停止 或 任务队列不为空
                // condition_variable::wait 会原子地释放锁并等待，
                // 被唤醒后会重新获取锁并检查条件
                condition.wait(lock, [this] { return stop || !tasks.empty(); });

                // 如果线程池已停止且任务队列为空，则工作线程可以安全退出
                if (stop && tasks.empty()) {
                    return;
                }

                // 从任务队列中获取一个任务
                task = std::move(tasks.front());
                tasks.pop();
            } // 锁在此处释放

            // 执行任务
            // 如果任务抛出异常，异常会被 packaged_task 捕获并存储在 future 中
            task();
        }
    }

    std::vector<std::thread> workers;       // 工作线程的集合
    std::queue<std::function<void()>> tasks; // 任务队列 (存储可调用对象)

    std::mutex queue_mutex;                 // 保护任务队列的互斥锁
    std::condition_variable condition;      // 用于线程同步的条件变量
    bool stop;                              // 标志，指示线程池是否应停止
};


#endif // THREADPOOL_H
